HTMLWidgets.widget({

    name: 'volcano',

    type: 'output',

    factory: function (el, width, height) {

        // TODO: define shared variables for this instance

        return {


            renderValue: function (x) {
                d3.select(el).append("svg");
                let width = 600;
                let height = 500;
                d3.select("svg")
                    .attr("width", width)
                    .attr("height", height);

                let sdpi = 3;
                let r = 3;
                let up = "#ff5050";
                let down = "#26d25d";
                let notsig = "rgb(101 179 254)";
                var color = {
                    green: down,
                    red: up,
                    blue: notsig,
                    black: "orange",
                    // "grap":"rgb(229, 229, 229)"
                }
                var round = {
                    green: r,
                    red: r,
                    blue: r,
                    black: r + 4,
                }
                //图例数组，格式可自定义
                var data_legend = [
                    {
                        "name": "Down",
                        "color": down,
                    },
                    {
                        "name": "Up",
                        "color": up,
                    },
                    {
                        "name": "NotSig",
                        "color": notsig,
                    },
                ];





                let xAxisLabel1 = 'Log[2]FC';
                let yAxisLabel1 = '-Log[10]PValue';
                let titlePosition = "0"; //0:left ; 1:middle; 2:right
                let titleSize = "16px";
                let titleFamily = "Arial";
                let titleWidth = "0";
                let titleText = x.titleName;
                let xFontSize = '14px';
                let yFontSize = '14px';
                let yFontWeight = '0';
                let xFontWeight = '0';
                let xScaleNumber = '5';
                let yScaleNumber = '5';

                let xangle = 0;
                let yangle = 0;
                let yfonttop = 5;
                let xfonttop = 5;



                let xLabelSize = '18px';
                let yLabelSize = '18px';
                let xLabelplot = 'middle';
                let yLabelplot = 'middle';
                let xLabelFamily = 'Arial';
                let yLabelFamily = 'Arial';
                let xLabelWidth = '0';
                let yLabelWidth = '0';
                let fc = '1.5';
                let pvalue = '0.05';
                let oldfc = '1.5';
                let oldpvalue = '0.05';

                let gridline = "0"; //0: 无网格; 1: 有网格
                let legendSize = '16px';
                let legendheight = 10;
                let legendwidth = 30;
                let legendPosition = "0"; //0:右方; 1: 下方; 2: 左方; 3: 上方
                let legendFamily = "Arial";

                let allFontFamily = "Arial";

                let shape = "circle";
                let shapeRound = 4;

                let infoFamily = "Arial";
                let infoSize = "16px";
                var arr = [];

                const svg = d3.select('svg');
                const margin = { top: 60, right: 100, bottom: 80, left: 100 };
                let innerWidth = width - margin.left - margin.right;
                let innerHeight = height - margin.top - margin.bottom;
                let xScale, yScale;
                let xAxisLabel = xAxisLabel1;
                let yAxisLabel = yAxisLabel1;
                let xValue = d => Math.log2(d['FC'] + 0);
                let yValue = d => Math.abs(Math.log10(d['PValue'] + 0));
                let xLabelPosition = innerWidth / 2;
                let yLabelPosition = -innerHeight / 2.5;
                let xgridtheme = 0;
                let ygridtheme = 0;
                let titlesite = 0;
                if (gridline == "1") {
                    console.log("网格线设置");
                    xgridtheme = -innerHeight;
                    ygridtheme = -innerWidth;
                }
                if (xLabelplot == 'left') {
                    xLabelPosition = '30px'
                } else if (xLabelplot == 'right') {
                    xLabelPosition = innerWidth - 30
                }
                if (yLabelplot == 'top') {
                    yLabelPosition = '0'
                } else if (yLabelplot == 'bottom') {
                    yLabelPosition = -innerHeight + 90
                }

                //标题位置设置
                if (titlePosition == "0") {
                    titlesite = innerWidth / 3;
                } else if (titlePosition == "1") {
                    titlesite = innerWidth / 1.3;
                } else {
                    titlesite = innerWidth / 1;
                }


                //初始化图例，将data_legend与图例绑定
                var legend = svg.selectAll(".legend")
                    .data(data_legend)
                    .enter().append("g")
                    .attr("class", "legend")
                    .attr("transform", function (d, i) {
                        if (legendPosition == 0) {
                            return "translate(-40," + (i * 20 + innerHeight / 1.7) + ")";
                        } else if (legendPosition == 3) {
                            return "translate(" + (-i * legendSize * shapeRound - innerWidth / 2) + ", 0)";
                        } else if (legendPosition == 1) {
                            return "translate(" + (-i * legendSize * shapeRound - innerWidth / 2) + "," + (innerHeight + 110) + ")";
                        } else if (legendPosition == 2) {
                            return "translate(" + (-innerHeight - 120) + "," + (i * 20 + 200) + ")";
                        }

                    });  //transform属性便是整个图例的坐标

                //绘制文字后方的颜色框或线
                legend.append("circle")
                    .attr("cx", width - 40)
                    .attr("cy", 12)
                    .attr('r', shapeRound)
                    .style("fill", function (d) {
                        return d.color
                    });

                //绘制图例文字
                legend.append("text")
                    .attr("x", width - 30)
                    .attr("y", 18)
                    .attr('font-family', legendFamily)
                    .attr("font-size", legendSize)
                    .style("text-align", "left")
                    .text(function (d) {
                        return d.name;
                    });

                //初始化散点图
                const renderinit = function (data) {
                    // Linear Scale: Data Space -> Screen Space;
                    xScale = d3.scaleLinear()
                        .domain([-d3.max(data, xValue), d3.max(data, xValue)]) // "extent" is equivalent to ;
                        .range([0, innerWidth]);

                    // Introducing y-Scale;
                    yScale = d3.scaleLinear()
                        .domain([0, d3.max(data, yValue)].reverse()) // remember to use reverse() to make y-axis start from the bottom;
                        .range([0, innerHeight]);



                    // 添加标题文本到SVG
                    svg.append("text")
                        .attr("class", "chart-title")
                        .attr("x", titlesite)
                        .attr('font-size', titleSize)
                        .attr('font-family', titleFamily)
                        .attr('font-weight', titleWidth)
                        .attr("y", 38)
                        .attr("text-anchor", "middle")
                        .text(titleText);

                    // The reason of using group is that nothing is rendered outside svg, so margin of svg is always blank while margin of group is rendered inside svg;
                    //绘制坐标轴
                    const g = svg.append('g').attr('id', 'maingroup')
                        .attr('transform', `translate(${margin.left}, ${margin.top})`)
                        .attr('font-size', '20px')

                    //绘制网格线
                    const g1 = svg.append('g').attr('id', 'maingroup1')
                        .attr('transform', `translate(${margin.left}, ${margin.top})`)
                        .attr('stroke-opacity', '0.07')

                    const xAxis1 = d3.axisBottom(xScale).ticks(xScaleNumber).tickSize(xgridtheme);
                    g1.append('g').call(xAxis1).attr('transform', `translate(${0}, ${innerHeight})`).style('font-size', '0')

                    const yAxis1 = d3.axisLeft(yScale).ticks(yScaleNumber).tickSize(ygridtheme);
                    g1.append('g').call(yAxis1).style('font-size', '0')


                    const xAxis = d3.axisBottom(xScale).ticks(xScaleNumber).tickSize(xgridtheme).tickSizeInner([5]).tickPadding(xfonttop);

                    // xAxis.attr("stroke", "#d4d4d4");
                    let xgroup = g.append('g').call(xAxis).attr('transform', `translate(${0}, ${innerHeight})`)
                        .style('font-size', xFontSize)
                        .style('font-weight', xFontWeight)
                        .attr('font-family', allFontFamily)

                    xgroup.append('text')
                        .attr('font-size', xLabelSize)
                        .attr('font-family', xLabelFamily)
                        .attr('font-weight', xLabelWidth)
                        .attr('y', 46)
                        .attr('x', xLabelPosition)
                        .attr('fill', '#333333')
                        .attr('transform', `rotate(0)`)
                        .text(xAxisLabel);

                    if (xangle !== 0) {
                        xgroup.selectAll('.tick text')
                            .attr('transform', `rotate(${xangle})`)
                            .style('text-anchor', 'end');
                    }

                    const yAxis = d3.axisLeft(yScale).ticks(yScaleNumber).tickSize(ygridtheme).tickSizeInner([5]).tickPadding(yfonttop);
                    let ygroup = g.append('g').call(yAxis)
                        .attr('font-size', yFontSize)
                        .attr('font-weight', yFontWeight)
                        .attr('font-family', allFontFamily)


                    ygroup.append('text')
                        .attr('font-size', yLabelSize)
                        .attr('font-family', yLabelFamily)
                        .attr('font-weight', yLabelWidth)
                        .attr('transform', `rotate(-90)`)
                        .attr('x', yLabelPosition)
                        .attr('y', -60)
                        .attr('fill', '#333333')
                        .text(yAxisLabel)

                    if (yangle !== 0) {
                        ygroup.selectAll('.tick text')
                            .attr('transform', `rotate(${yangle})`)
                            .style('text-anchor', 'end');
                    }

                    const yaveline = yScale(Math.abs(Math.log10(pvalue)))
                    //水平辅助线
                    const xline = svg.append("line")
                        .attr("x1", 0)
                        .attr("x2", width - 200)
                        .attr("y1", yaveline)
                        .attr("y2", yaveline)
                        .attr("stroke-width", 1.5)
                        .attr("stroke", "black")
                        .attr("stroke-dasharray", "5,5")
                        .attr('transform', `translate(${margin.left}, ${margin.top})`);
                    //垂直辅助线
                    const lxline = xScale(Math.log2(1 / fc));
                    const rxline = xScale(Math.log2(fc));
                    console.log("lxline" + lxline);
                    //垂直辅助线
                    const ylline = svg.append("line")
                        .attr("x1", lxline)
                        .attr("x2", lxline)
                        .attr("y1", 0)
                        .attr("y2", height - 130)
                        .attr("stroke-width", 1.5)
                        .attr("stroke", "black")
                        .attr("stroke-dasharray", "5,5")
                        .attr('transform', `translate(${margin.left}, ${margin.top})`);

                    const yrline = svg.append("line")
                        .attr("x1", rxline)
                        .attr("x2", rxline)
                        .attr("y1", 0)
                        .attr("y2", height - 130)
                        .attr("stroke-width", 1.5)
                        .attr("stroke", "black")
                        .attr("stroke-dasharray", "5,5")
                        .attr('transform', `translate(${margin.left}, ${margin.top})`);
                };


                const renderUpdate = function (data) {
                    let tooltip = d3.select('body')
                        .append('div')
                        .style('position', 'absolute')
                        .style('z-index', '10')
                        .style('color', '#fff')
                        .style('background', 'black')
                        .style('width', '100px')
                        .style('height', '60px')
                        .style('text-align', 'center')
                        .style('padding-top', '5px')
                        .style('visibility', 'visible')   // 是否可见（一开始设置为隐藏）
                        .style('font-size', '12px')
                        .style('font-weight', 'bold')
                        .text('');

                    const clickarr = [];
                    let infoBoxStartPos = {};
                    const g = d3.select("#maingroup");
                    let circleupdates = g.selectAll('circle').data(data, d => d['Name']);
                    let circleenter = circleupdates.enter().append('circle')
                        .attr('cx', d => xScale(xValue(d)))
                        .attr('cy', d => yScale(yValue(d)))
                        .attr('r', d => round[d['group']])
                        .attr('fill', d => color[d['group']])
                        .attr('opacity', 0.6)

                        .on('click', function (d, i) {
                            if (arr.indexOf(d.Name) == -1) {
                                arr.push(d.Name)
                                const dd = d;
                                const infoBox = svg.append("text")
                                    .attr("x", xScale(xValue(d)) + 60)
                                    .attr("y", yScale(yValue(d)) + 42)
                                    .style("fill", "#000")
                                    .style("font-family", infoFamily)
                                    .style('font-size', infoSize)
                                    .text(d.Name);

                                const lines = svg.append("line")
                                    .attr("x1", xScale(xValue(d)) + 80)
                                    .attr("y1", yScale(yValue(d)) + 42)
                                    .attr("x2", xScale(xValue(d)) + 100)
                                    .attr("y2", yScale(yValue(d)) + 60)
                                    .attr("stroke-width", 1)
                                    .attr("stroke", "black");

                                const drag = d3.drag()
                                    .on("start", dragstarted)
                                    .on("drag", dragged);

                                infoBox.call(drag);

                                function dragstarted(event, d) {
                                    d3.select(this).raise();
                                    infoBoxStartPos = { x: d3.event.x, y: d3.event.y };
                                }

                                function dragged(event, d) {

                                    infoBox.attr("x", d3.event.x)
                                        .attr("y", d3.event.y);

                                    lines.attr("x1", +infoBox.attr("x") + 20)
                                        .attr("y1", +infoBox.attr("y") + 6)
                                        .attr("x2", xScale(xValue(dd)) + 100)
                                        .attr("y2", yScale(yValue(dd)) + 60);
                                }
                            }

                            // 显示当前点击点的信息框
                            if (!arr.includes(d)) {
                                arr.push(d);
                                d3.select(this)
                                    // .attr('fill','black')
                                    .attr('r', r + 4)
                                    .attr('opacity', 1)
                                emit('selectarr', JSON.stringify(arr))

                            } else {
                                arr.splice(arr.indexOf(d), 1)
                                d3.select(this)
                                    .attr('r', r)
                                    .attr('opacity', 0.6)
                                emit('selectarr', JSON.stringify(arr))
                            }

                        })
                        .on('mouseover', function (d, i) {
                            d3.select(this)
                                .attr('opacity', 1)
                                .attr('stroke', d => color[d['group']])
                                .attr('stroke-width', '5px')
                                .attr('stroke-opacity', '0.6')
                                .attr('cursor', 'pointer')

                            return tooltip.style('visibility', 'visible')
                                .text("Name:" + d.Name + "  " + "FC:" + d.FC.toFixed(2) + "  " + "PValue:" + d.PValue.toExponential(2))
                        })
                        .on('mousemove', function (d, i) {
                            d3.select(this)
                                .attr('stroke', d => color[d['group']])
                                .attr('stroke-width', '5px')
                                .attr('stroke-opacity', '0.6')
                                .attr('opacity', 1)
                            return tooltip.style('top', (event.pageY - 10) + 'px').style('left', (event.pageX + 10) + 'px')
                        })
                        .on('mouseout', function (d, i) {
                            d3.select(this)
                                .attr('opacity', 0.6)
                                .attr('stroke-width', '0')
                            return tooltip.style('visibility', 'hidden')
                        });


                    //套索

                }
                // const data = [
                //     { Name: "id1", FC: "0.1", PValue: "0.0078", Maker: "0" },
                //     { Name: "id1", FC: "0.06", PValue: "0.00129", Maker: "0" },
                //     { Name: "id1", FC: "0.3", PValue: "1.3", Maker: "0" },
                //     { Name: "id1", FC: "17", PValue: "0.00497", Maker: "0" },
                //     { Name: "id1", FC: "0.5", PValue: "0.0099", Maker: "0" },
                //     { Name: "id1", FC: "7", PValue: "0.0013", Maker: "0" },
                //     { Name: "id1", FC: "10", PValue: "0.0079", Maker: "0" },
                //     { Name: "id1", FC: "0.8", PValue: "3.0", Maker: "0" },
                //     { Name: "id1", FC: "0.9", PValue: "2.0", Maker: "0" },
                // ]
                const data = HTMLWidgets.dataframeToD3(x.data);
                
                data.forEach(d => {
                    d['FC'] = + (d['FC']);
                    d['PValue'] = + (d['PValue']);
                    d['Marker'] = + (d['Marker']);
                });
                if (data.some(item => item.hasOwnProperty('group'))) {
                    console.log(pvalue);
                    console.log(fc);
                    for (let i = 0; i < data.length; i++) {
                        const e = data[i];
                        if (e.group == "white" || oldfc != fc || oldpvalue != pvalue) {
                            if (e.PValue > pvalue) {
                                e.group = "blue";
                            } else {
                                if (e.FC < 1 / fc) {
                                    e.group = "green"
                                } else if (e.FC > fc) {
                                    e.group = "red"
                                } else {
                                    e.group = "blue"
                                }
                            }
                        }
                    }
                    console.log("更改数据");

                } else {
                    console.log("添加颜色");
                    console.log(pvalue);
                    console.log(fc);

                    for (let i = 0; i < data.length; i++) {
                        const ele = data[i];

                        if (ele.PValue > pvalue) {
                            ele.group = "blue";
                        } else {
                            if (ele.FC < 1 / fc) {
                                ele.group = "green"
                            } else if (ele.FC > fc) {
                                ele.group = "red"
                            } else {
                                ele.group = "blue"
                            }
                        }
                    }
                }
                for (let i = 0; i < data.length; i++) {
                    const e = data[i];
                    if (e.PValue == 0) {
                        data.splice(i, 1)
                    }

                }

                renderinit(data);
                renderUpdate(data);




            },

            resize: function (width, height) {

                // TODO: code to re-render the widget with a new size

            }

        };
    }
});
